home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / graphic / jpegsrc4.zip / JMEMMGR.C < prev    next >
C/C++ Source or Header  |  1992-11-01  |  39KB  |  1,103 lines

  1. /*
  2.  * jmemmgr.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file provides the standard system-independent memory management
  9.  * routines.  This code is usable across a wide variety of machines; most
  10.  * of the system dependencies have been isolated in a separate file.
  11.  * The major functions provided here are:
  12.  *   * bookkeeping to allow all allocated memory to be freed upon exit;
  13.  *   * policy decisions about how to divide available memory among the
  14.  *     various large arrays;
  15.  *   * control logic for swapping virtual arrays between main memory and
  16.  *     backing storage.
  17.  * The separate system-dependent file provides the actual backing-storage
  18.  * access code, and it contains the policy decision about how much total
  19.  * main memory to use.
  20.  * This file is system-dependent in the sense that some of its functions
  21.  * are unnecessary in some systems.  For example, if there is enough virtual
  22.  * memory so that backing storage will never be used, much of the big-array
  23.  * control logic could be removed.  (Of course, if you have that much memory
  24.  * then you shouldn't care about a little bit of unused code...)
  25.  *
  26.  * These routines are invoked via the methods alloc_small, free_small,
  27.  * alloc_medium, free_medium, alloc_small_sarray, free_small_sarray,
  28.  * alloc_small_barray, free_small_barray, request_big_sarray,
  29.  * request_big_barray, alloc_big_arrays, access_big_sarray, access_big_barray,
  30.  * free_big_sarray, free_big_barray, and free_all.
  31.  */
  32.  
  33. #define AM_MEMORY_MANAGER    /* we define big_Xarray_control structs */
  34.  
  35. #include "jinclude.h"
  36. #include "jmemsys.h"        /* import the system-dependent declarations */
  37.  
  38. #ifndef NO_GETENV
  39. #ifdef INCLUDES_ARE_ANSI
  40. #include <stdlib.h>        /* to declare getenv() */
  41. #else
  42. extern char * getenv PP((const char * name));
  43. #endif
  44. #endif
  45.  
  46.  
  47. /*
  48.  * On many systems it is not necessary to distinguish alloc_small from
  49.  * alloc_medium; the main case where they must be distinguished is when
  50.  * FAR pointers are distinct from regular pointers.  However, you might
  51.  * want to keep them separate if you have different system-dependent logic
  52.  * for small and large memory requests (i.e., jget_small and jget_large
  53.  * do different things).
  54.  */
  55.  
  56. #ifdef NEED_FAR_POINTERS
  57. #define NEED_ALLOC_MEDIUM    /* flags alloc_medium really exists */
  58. #endif
  59.  
  60.  
  61. /*
  62.  * Many machines require storage alignment: longs must start on 4-byte
  63.  * boundaries, doubles on 8-byte boundaries, etc.  On such machines, malloc()
  64.  * always returns pointers that are multiples of the worst-case alignment
  65.  * requirement, and we had better do so too.  This means the headers that
  66.  * we tack onto allocated structures had better have length a multiple of
  67.  * the alignment requirement.
  68.  * There isn't any really portable way to determine the worst-case alignment
  69.  * requirement.  In this code we assume that the alignment requirement is
  70.  * multiples of sizeof(align_type).  Here we define align_type as double;
  71.  * with this definition, the code will run on all machines known to me.
  72.  * If your machine has lesser alignment needs, you can save a few bytes
  73.  * by making align_type smaller.
  74.  */
  75.  
  76. typedef double align_type;
  77.  
  78.  
  79. /*
  80.  * Some important notes:
  81.  *   The allocation routines provided here must never return NULL.
  82.  *   They should exit to error_exit if unsuccessful.
  83.  *
  84.  *   It's not a good idea to try to merge the sarray and barray routines,
  85.  *   even though they are textually almost the same, because samples are
  86.  *   usually stored as bytes while coefficients are shorts.  Thus, in machines
  87.  *   where byte pointers have a different representation from word pointers,
  88.  *   the resulting machine code could not be the same.
  89.  */
  90.  
  91.  
  92. static external_methods_ptr methods; /* saved for access to error_exit */
  93.  
  94.  
  95. #ifdef MEM_STATS        /* optional extra stuff for statistics */
  96.  
  97. /* These macros are the assumed overhead per block for malloc().
  98.  * They don't have to be accurate, but the printed statistics will be
  99.  * off a little bit if they are not.
  100.  */
  101. #define MALLOC_OVERHEAD  (SIZEOF(void *)) /* overhead for jget_small() */
  102. #define MALLOC_FAR_OVERHEAD  (SIZEOF(void FAR *)) /* for jget_large() */
  103.  
  104. static long total_num_small = 0;    /* total # of small objects alloced */
  105. static long total_bytes_small = 0;    /* total bytes requested */
  106. static long cur_num_small = 0;        /* # currently alloced */
  107. static long max_num_small = 0;        /* max simultaneously alloced */
  108.  
  109. #ifdef NEED_ALLOC_MEDIUM
  110. static long total_num_medium = 0;    /* total # of medium objects alloced */
  111. static long total_bytes_medium = 0;    /* total bytes requested */
  112. static long cur_num_medium = 0;        /* # currently alloced */
  113. static long max_num_medium = 0;        /* max simultaneously alloced */
  114. #endif
  115.  
  116. static long total_num_sarray = 0;    /* total # of sarray objects alloced */
  117. static long total_bytes_sarray = 0;    /* total bytes requested */
  118. static long cur_num_sarray = 0;        /* # currently alloced */
  119. static long max_num_sarray = 0;        /* max simultaneously alloced */
  120.  
  121. static long total_num_barray = 0;    /* total # of barray objects alloced */
  122. static long total_bytes_barray = 0;    /* total bytes requested */
  123. static long cur_num_barray = 0;        /* # currently alloced */
  124. static long max_num_barray = 0;        /* max simultaneously alloced */
  125.  
  126.  
  127. LOCAL void
  128. print_mem_stats (void)
  129. {
  130.   /* since this is only a debugging stub, we can cheat a little on the
  131.    * trace message mechanism... helpful 'cuz trace_message can't handle longs.
  132.    */
  133.   fprintf(stderr, "total_num_small = %ld\n", total_num_small);
  134.   fprintf(stderr, "total_bytes_small = %ld\n", total_bytes_small);
  135.   if (cur_num_small)
  136.     fprintf(stderr, "cur_num_small = %ld\n", cur_num_small);
  137.   fprintf(stderr, "max_num_small = %ld\n", max_num_small);
  138.   
  139. #ifdef NEED_ALLOC_MEDIUM
  140.   fprintf(stderr, "total_num_medium = %ld\n", total_num_medium);
  141.   fprintf(stderr, "total_bytes_medium = %ld\n", total_bytes_medium);
  142.   if (cur_num_medium)
  143.     fprintf(stderr, "cur_num_medium = %ld\n", cur_num_medium);
  144.   fprintf(stderr, "max_num_medium = %ld\n", max_num_medium);
  145. #endif
  146.   
  147.   fprintf(stderr, "total_num_sarray = %ld\n", total_num_sarray);
  148.   fprintf(stderr, "total_bytes_sarray = %ld\n", total_bytes_sarray);
  149.   if (cur_num_sarray)
  150.     fprintf(stderr, "cur_num_sarray = %ld\n", cur_num_sarray);
  151.   fprintf(stderr, "max_num_sarray = %ld\n", max_num_sarray);
  152.   
  153.   fprintf(stderr, "total_num_barray = %ld\n", total_num_barray);
  154.   fprintf(stderr, "total_bytes_barray = %ld\n", total_bytes_barray);
  155.   if (cur_num_barray)
  156.     fprintf(stderr, "cur_num_barray = %ld\n", cur_num_barray);
  157.   fprintf(stderr, "max_num_barray = %ld\n", max_num_barray);
  158. }
  159.  
  160. #endif /* MEM_STATS */
  161.  
  162.  
  163. LOCAL void
  164. out_of_memory (int which)
  165. /* Report an out-of-memory error and stop execution */
  166. /* If we compiled MEM_STATS support, report alloc requests before dying */
  167. {
  168. #ifdef MEM_STATS
  169.   if (methods->trace_level <= 0) /* don't do it if free_all() will */
  170.     print_mem_stats();        /* print optional memory usage statistics */
  171. #endif
  172.   ERREXIT1(methods, "Insufficient memory (case %d)", which);
  173. }
  174.  
  175.  
  176. /*
  177.  * Management of "small" objects.
  178.  * These are all-in-memory, and are in near-heap space on an 80x86.
  179.  */
  180.  
  181. typedef union small_struct * small_ptr;
  182.  
  183. typedef union small_struct {
  184.     small_ptr next;        /* next in list of allocated objects */
  185.     align_type dummy;    /* ensures alignment of following storage */
  186.       } small_hdr;
  187.  
  188. static small_ptr small_list;    /* head of list */
  189.  
  190.  
  191. METHODDEF void *
  192. alloc_small (size_t sizeofobject)
  193. /* Allocate a "small" object */
  194. {
  195.   small_ptr result;
  196.  
  197.   sizeofobject += SIZEOF(small_hdr); /* add space for header */
  198.  
  199. #ifdef MEM_STATS
  200.   total_num_small++;
  201.   total_bytes_small += sizeofobject + MALLOC_OVERHEAD;
  202.   cur_num_small++;
  203.   if (cur_num_small > max_num_small) max_num_small = cur_num_small;
  204. #endif
  205.  
  206.   result = (small_ptr) jget_small(sizeofobject);
  207.   if (result == NULL)
  208.     out_of_memory(1);
  209.  
  210.   result->next = small_list;
  211.   small_list = result;
  212.   result++